说明:
Swift
使用自动引用计数(ARC)
机制来跟踪和管理你的应用程序的内存。
适用类型:类(结构体和枚举是值类型)
16.1 自动引用计数的工作机制
说明:当你每次创建一个类的新的实例的时候,
ARC
会分配一大块内存用来储存实例的信息。内存中会包含实例的类型信息,以及这个实例所有相关属性的值。强引用:无论将实例赋值给
属性
、常量
还是变量
,都会对此实例创建强引用
。当一个实例的引用计数为0时,实例将被ARC
销毁。
16.2 自动引用计数实践
1 | //1.创建类 |
16.3 类实例之间的循环强引用
循环强引用:两个类实例互相保持对方的
强引用
,并让对方不被销毁。
解决思路:通过定义类之间的关系为弱引用
或无主引用
,以此替代强引用。
细分情况 | 分析(两个实例各自引用对方的属性) | 解决思路 |
---|---|---|
情况1 | 都允许为nil |
其中一个属性使用弱引用 |
情况2 | 一个允许为nil ,另一个不允许 |
不允许为nil 的属性使用无主引用 |
情况3 | 都不允许为nil |
一个使用无主引用 ,一个使用隐式解析可选属性 |
16.4 解决实例之间的循环强引用
解决方法:用弱引用或无主导引用替代强引用
- 弱引用(weak reference)适用:生命周期中会变为
nil
的实例- 无主引用(unowned reference)适用:初始化赋值后再也不会被赋值为nil的实例
16.4.1 弱引用
关键字:
weak
说明:弱引用不会对其引用的实例保持强引用,因而不会阻止ARC
销毁被引用的实例
- 因为弱引用可以没有值,你必须将每一个弱引用声明为可选类型
- 弱引用必须被声明为变量(
var
),表明需要在运行时修改ARC
在引用的实例被销毁之后自动将弱引用关联的变量或属性赋值为nil
语法:声明
属性
或者变量
时,在前面加上weak
关键字
1 | class Person { |
16.4.2 无主引用
关键字:
unowned
说明:在声明属性或者变量时,在前面加上关键字unowned表示这是一个无主引用。
- 不会牢牢保持住引用的实例
- 总是被定义为非可选型(永远是有值的),总是可以被直接访问
ARC
无法在实例被销毁后将无主引用设为nil
(因为非可选类型的变量不允许被赋值为nil
)注意:使用无主引用,必须确保引用始终指向一个未销毁的实例。
1 | //用户 |
16.4.3 无主引用以及隐式可选属性
说明:两个属性都必须有值,并且初始化完成后永远不会为
nil
。在这种场景中,需要一个类使用无主属性
,而另外一个类使用隐式解析可选属性
。
1 | //国家 |
16.5 闭包引起的循环强引用
原理:实例内部的闭包捕获
self
,从而在实例和闭包之间产生循环强引用。
情景:
- 闭包中访问实例的属性(
self.someproperty
)- 闭包中访问实例的方法(
self.someMethod
)
1 | class HTMLElement { |
16.6 解决闭包引起的循环强引用
捕获列表:定义了闭包体内捕获一个或多个引用类型的规则(
弱引用
或无主引用
)。
解决方式:在定义闭包
时同时定义捕获列表
作为闭包的一部分
注意:只要在闭包中使用self
的成员,就要用self.someProperty
或self.someMethod
16.6.1 定义捕获列表
捕获列表:[{
weak
|unknowed
} {实例}, {weak
|unknowed
} {实例}, …]
说明:捕获列表中的每一项都由一对元素组成,一个元素是weak
或unowned
关键字,另一个元素是类实例的引用
- 捕获列表放在闭包参数和返回值之前(需要指出闭包的参数和返回值类型):有参数列表和返回类型
1 | //类或结构体中定义一个闭包 |
- 通过上下文推断(省略类型说明):闭包没有定义参数列表或返回值时
1 | lazy var someClosure:()->String = { |
16.6.2 弱引用和无主引用
说明:
捕获列表
中引用的引用类型可以是weak
或unowned
,选择的依据是
- 捕获的引用绝对不会为
nil
:将闭包内的捕获定义为无主引用
- 捕获引用有可能为
nil
:将闭包内的捕获定义为弱引用
(可选型)
1 | class HTMLElement { |